//
// Created by wkm on 2024-04-23.
//

#include "aes128en.h"

void aes128en::prc_aes128() {
    if (reset) {
        compute_round_NO = 0;
        done_next_state = waiting_task;
        done = waiting_task;
        for (int i = 0; i <= 10; i++) {
            key[i] = 0;
            res[i] = 0;
        }
        sk_reset.write(true);
        sr_reset.write(true);
        mx_reset.write(true);
        sk_start_first_flag = true;
    }

    if (start && done == waiting_task) {
        sk_reset.write(false);
        sr_reset.write(false);
        mx_reset.write(false);
        cout << "66" << endl;
        key[0] = key1;
        key[1] = key2;
        key[2] = key3;
        key[3] = key4;
        key[4] = key5;
        key[5] = key6;
        key[6] = key7;
        key[7] = key8;
        key[8] = key9;
        key[9] = key10;
        key[10] = key11;
        key[11] = key12;
        key[12] = key13;
        key[13] = key14;
        key[14] = key15;
        key[15] = key16;
        res[0] = pt1;
        res[1] = pt2;
        res[2] = pt3;
        res[3] = pt4;
        res[4] = pt5;
        res[5] = pt6;
        res[6] = pt7;
        res[7] = pt8;
        res[8] = pt9;
        res[9] = pt10;
        res[10] = pt11;
        res[11] = pt12;
        res[12] = pt13;
        res[13] = pt14;
        res[14] = pt15;
        res[15] = pt16;
        done_next_state = preparing_task;
    }

    if (done == preparing_task) {
        // 准备阶段，主要是准备轮密钥

        // 密钥生成，在start前要先准备好数据
        init_key_1 = key[0];
        init_key_2 = key[1];
        init_key_3 = key[2];
        init_key_4 = key[3];
        init_key_5 = key[4];
        init_key_6 = key[5];
        init_key_7 = key[6];
        init_key_8 = key[7];
        init_key_9 = key[8];
        init_key_10 = key[9];
        init_key_11 = key[10];
        init_key_12 = key[11];
        init_key_13 = key[12];
        init_key_14 = key[13];
        init_key_15 = key[14];
        init_key_16 = key[15];
        if (sk_start_first_flag) {
            sk_start = true;
            sk_start_first_flag = false;
        } else {
            sk_start = false;
        }

        if (sk_done == task_finished) {
            done_next_state = computing_task;
        }
    }

    if (done == computing_task) {
        switch (op_state) {
            case bytesub:
                cout << "bytesub, compute_round_NO: " << compute_round_NO << endl;
                sk_get_round = compute_round_NO + 1;
                // 因为每一轮的循环的最后，都设为了true，所以此处改为false，让代码可以执行下去
                sr_reset.write(false);
                mx_reset.write(false);
                if (compute_round_NO >= 1 && compute_round_NO <= 10) {
                    sbox_input_1 = res[0];
                    sbox_input_2 = res[1];
                    sbox_input_3 = res[2];
                    sbox_input_4 = res[3];
                    sbox_input_5 = res[4];
                    sbox_input_6 = res[5];
                    sbox_input_7 = res[6];
                    sbox_input_8 = res[7];
                    sbox_input_9 = res[8];
                    sbox_input_10 = res[9];
                    sbox_input_11 = res[10];
                    sbox_input_12 = res[11];
                    sbox_input_13 = res[12];
                    sbox_input_14 = res[13];
                    sbox_input_15 = res[14];
                    sbox_input_16 = res[15];
                    if (sbox_done == task_finished) {
                        res[0] = sbox_output_1;
                        res[1] = sbox_output_2;
                        res[2] = sbox_output_3;
                        res[3] = sbox_output_4;
                        res[4] = sbox_output_5;
                        res[5] = sbox_output_6;
                        res[6] = sbox_output_7;
                        res[7] = sbox_output_8;
                        res[8] = sbox_output_9;
                        res[9] = sbox_output_10;
                        res[10] = sbox_output_11;
                        res[11] = sbox_output_12;
                        res[12] = sbox_output_13;
                        res[13] = sbox_output_14;
                        res[14] = sbox_output_15;
                        res[15] = sbox_output_16;
                        // TODO 可能会因为sbox数据更新不及时 导致bug
                        sbox_enread = false;
                        op_state_next = rowshift;
                        sr_reset = false;
                        cout << "ciphertext sub" << compute_round_NO << ": " << hex
                             << res[0] << "," << res[1] << "," << res[2] << "," << res[3] << ","
                             << res[4] << "," << res[5] << "," << res[6] << "," << res[7] << ","
                             << res[8] << "," << res[9] << "," << res[10] << "," << res[11] << ","
                             << res[12] << "," << res[13] << "," << res[14] << "," << res[15]
                             << endl;
                    } else {
                        sbox_enread = true;
                    }
                } else {
//                    sr_reset = true;
                    op_state_next = rowshift;
                }
                break;
            case rowshift:
                cout << "rowshift, compute_round_NO: " << compute_round_NO << endl;
                if (compute_round_NO >= 1 && compute_round_NO <= 10) {
                    cout << "sr_done:" << sr_done << endl;
//                    sr_reset = false;
                    sr_in_1 = res[0];
                    sr_in_2 = res[1];
                    sr_in_3 = res[2];
                    sr_in_4 = res[3];
                    sr_in_5 = res[4];
                    sr_in_6 = res[5];
                    sr_in_7 = res[6];
                    sr_in_8 = res[7];
                    sr_in_9 = res[8];
                    sr_in_10 = res[9];
                    sr_in_11 = res[10];
                    sr_in_12 = res[11];
                    sr_in_13 = res[12];
                    sr_in_14 = res[13];
                    sr_in_15 = res[14];
                    sr_in_16 = res[15];
                    sr_start = true;
                    if (sr_done == task_finished) {
                        res[0] = sr_out_1;
                        res[1] = sr_out_2;
                        res[2] = sr_out_3;
                        res[3] = sr_out_4;
                        res[4] = sr_out_5;
                        res[5] = sr_out_6;
                        res[6] = sr_out_7;
                        res[7] = sr_out_8;
                        res[8] = sr_out_9;
                        res[9] = sr_out_10;
                        res[10] = sr_out_11;
                        res[11] = sr_out_12;
                        res[12] = sr_out_13;
                        res[13] = sr_out_14;
                        res[14] = sr_out_15;
                        res[15] = sr_out_16;

//                        sr_reset = true;
                        sr_start = false;
                        op_state_next = mixcolumn;
                        cout << "ciphertext shift" << compute_round_NO << ": " << hex
                             << res[0] << "," << res[1] << "," << res[2] << "," << res[3] << ","
                             << res[4] << "," << res[5] << "," << res[6] << "," << res[7] << ","
                             << res[8] << "," << res[9] << "," << res[10] << "," << res[11] << ","
                             << res[12] << "," << res[13] << "," << res[14] << "," << res[15]
                             << endl;
                    }
                } else {
                    op_state_next = mixcolumn;
                }
                break;
            case mixcolumn:
                cout << "mixcolumn, compute_round_NO: " << compute_round_NO << endl;
                if (compute_round_NO >= 1 && compute_round_NO <= 9) {
                    mx_in_1 = res[0];
                    mx_in_2 = res[1];
                    mx_in_3 = res[2];
                    mx_in_4 = res[3];
                    mx_in_5 = res[4];
                    mx_in_6 = res[5];
                    mx_in_7 = res[6];
                    mx_in_8 = res[7];
                    mx_in_9 = res[8];
                    mx_in_10 = res[9];
                    mx_in_11 = res[10];
                    mx_in_12 = res[11];
                    mx_in_13 = res[12];
                    mx_in_14 = res[13];
                    mx_in_15 = res[14];
                    mx_in_16 = res[15];
                    mx_reset = false;
                    mx_start = true;
                    if (mx_done == task_finished) {
                        res[0] = mx_out_1;
                        res[1] = mx_out_2;
                        res[2] = mx_out_3;
                        res[3] = mx_out_4;
                        res[4] = mx_out_5;
                        res[5] = mx_out_6;
                        res[6] = mx_out_7;
                        res[7] = mx_out_8;
                        res[8] = mx_out_9;
                        res[9] = mx_out_10;
                        res[10] = mx_out_11;
                        res[11] = mx_out_12;
                        res[12] = mx_out_13;
                        res[13] = mx_out_14;
                        res[14] = mx_out_15;
                        res[15] = mx_out_16;
                        mx_reset = true;
                        mx_start = false;
                        op_state_next = round_xor;
                        cout << "ciphertext mx" << compute_round_NO << ": " << hex
                             << res[0] << "," << res[1] << "," << res[2] << "," << res[3] << ","
                             << res[4] << "," << res[5] << "," << res[6] << "," << res[7] << ","
                             << res[8] << "," << res[9] << "," << res[10] << "," << res[11] << ","
                             << res[12] << "," << res[13] << "," << res[14] << "," << res[15]
                             << endl;
                    }
                } else {
                    op_state_next = round_xor;
                }
                break;
            case round_xor:
                cout << "round_xor, compute_round_NO: " << compute_round_NO << endl;
                // 轮密钥加
                if (compute_round_NO >= 0 && compute_round_NO <= 10) {
                    if (sk_can_read == task_finished) {
                        res[0] ^= round_key_1.read();
                        res[1] ^= round_key_2.read();
                        res[2] ^= round_key_3.read();
                        res[3] ^= round_key_4.read();
                        res[4] ^= round_key_5.read();
                        res[5] ^= round_key_6.read();
                        res[6] ^= round_key_7.read();
                        res[7] ^= round_key_8.read();
                        res[8] ^= round_key_9.read();
                        res[9] ^= round_key_10.read();
                        res[10] ^= round_key_11.read();
                        res[11] ^= round_key_12.read();
                        res[12] ^= round_key_13.read();
                        res[13] ^= round_key_14.read();
                        res[14] ^= round_key_15.read();
                        res[15] ^= round_key_16.read();
                        cout << "ciphertext xor" << compute_round_NO << ": " << hex
                             << res[0] << "," << res[1] << "," << res[2] << "," << res[3] << ","
                             << res[4] << "," << res[5] << "," << res[6] << "," << res[7] << ","
                             << res[8] << "," << res[9] << "," << res[10] << "," << res[11] << ","
                             << res[12] << "," << res[13] << "," << res[14] << "," << res[15]
                             << endl;
                        compute_round_NO += 1;
                        op_state_next = bytesub;
                        // 一轮循环已结束，需要对其状态重置一下
                        sr_reset.write(true);
                        mx_reset.write(true);
                    }
                } else {
                    op_state_next = goodjob;
                }
                break;
            default:;
                ct1 = res[0];
                ct2 = res[1];
                ct3 = res[2];
                ct4 = res[3];
                ct5 = res[4];
                ct6 = res[5];
                ct7 = res[6];
                ct8 = res[7];
                ct9 = res[8];
                ct10 = res[9];
                ct11 = res[10];
                ct12 = res[11];
                ct13 = res[12];
                ct14 = res[13];
                ct15 = res[14];
                ct16 = res[15];
                done_next_state = task_finished;
        }
    }

    done = done_next_state;
    op_state = op_state_next;
}